package com.strong.config;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.db.sql.SqlExecutor;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceBuilder;
import com.strong.utils.StrongUtils;
import com.strong.utils.exception.StrongRuntimeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import static com.strong.system.SystemConstants.STR_DIRECTORY_DATA;
import static com.strong.system.SystemConstants.STR_DIRECTORY_GIT_IGNORE;
import static com.strong.utils.security.SecurityUtils.SM2_OBJ;

/**
 * DruidDataSource配置
 *
 * @author simen
 * @date 2022/11/14
 */
@Slf4j
@Configuration
public class DataSourceConfig {

    /**
     * 数据库名称
     */
    @Value("${strong.database-name}")
    private String databaseName;

    /**
     * 驱动类名
     */
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    /**
     * 数据库用户名
     */
    @Value("${spring.datasource.username}")
    private String username;

    /**
     * 数据库密码
     */
    @Value("${spring.datasource.password}")
    private String password;

    /**
     * 项目启动时是否初始化数据库
     */
    @Value("${application.init-database}")
    private Boolean initDatabase;

    /**
     * 从默认参数配置数据源
     *
     * @return {@link DataSource}
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.druid")
    public DataSource getDataSource() {
        DruidDataSource druidDataSource = DruidDataSourceBuilder.create().build();

        try {
            // 使用私钥解密账号密码，注入数据源
            druidDataSource.setUsername(SM2_OBJ.decryptStr(username, KeyType.PrivateKey));
            druidDataSource.setPassword(SM2_OBJ.decryptStr(password, KeyType.PrivateKey));
        } catch (Exception exception) {
            throw new StrongRuntimeException("请检查密钥文件及Springboot配置文件内的加密后的数据库账号密码是否匹配。可使用KeyUtils重新生成");
        }

        // 如果是H2数据库，则注入加载
        if (StrUtil.equals(org.h2.Driver.class.getName(), driverClassName)) {
            // 配置数据库URL
            String strDatabaseFile = StrongUtils.getStaticPath(STR_DIRECTORY_GIT_IGNORE, databaseName);
            String strJdbcUrl = String.format("jdbc:h2:tcp://localhost:9092/%s;", strDatabaseFile);
            log.info("连接数据库：{}", strJdbcUrl);
            druidDataSource.setUrl(strJdbcUrl);

            // 如果系统配置初始化数据库
            if (ObjUtil.isNotNull(initDatabase) && initDatabase) {
                // 【测试代码】删除原数据库文件
                log.info("删除数据库文件 [{}] {}", strDatabaseFile,
                        FileUtil.del(strDatabaseFile + ".mv.db") ? "成功" : "失败"
                );

                // 初始化数据库
                initH2Database(druidDataSource, strJdbcUrl);
            }

            log.info("成功连接H2数据库 [{}]", strJdbcUrl);
        }
        return druidDataSource;
    }

    /**
     * 初始化数据库
     *
     * @param druidDataSource 数据源对象
     * @param strJdbcUrl      JDBC url
     */
    private static void initH2Database(DruidDataSource druidDataSource, String strJdbcUrl) {
        try {
            Connection connection = DriverManager.getConnection(strJdbcUrl + String.format("USER=%s;PASSWORD=%s;",
                    druidDataSource.getUsername(), druidDataSource.getPassword()));
            SqlExecutor.execute(connection, FileUtil.readUtf8String(StrongUtils.getStaticPath(STR_DIRECTORY_DATA, "test.sql")));
            log.info("使用test.sql初始化数据库成功");
        } catch (SQLException e) {
            log.info("使用test.sql初始化数据库失败");
            throw new RuntimeException(e);
        }
    }

}
